package cn.xiaolang.function.network.io;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.Future;

/**
 * 异步非阻塞IO
 * <p>
 * 1. AIO的性价比应该是优于NIO的，而实际情况却是大多数人更偏爱NIO通信框架：Netty。
 * 2. NIO和AIO在unix系统上使用的都是epoll模式
 * 3. Linux内核自2.6版本起已支持AIO模式。
 * 4. JDK7引入了Asynchronous I/O， 即AIO
 *
 * @author Dean
 * @date 2022-02-14
 */
public class SocketServerAIO {

    public static void main(String[] args) {
        try {
            final AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open();
            listener.bind(new InetSocketAddress(10010));
            System.out.println("server up use port:" + 10010);
            final String connName = "DN-client";
            // 监听, attachment是用来传递参数进去的
            listener.accept(connName, new CompletionHandler<AsynchronousSocketChannel, Object>() {

                @Override
                public void completed(AsynchronousSocketChannel client, Object attachment) {
                    // 循环监听
                    listener.accept(connName, this);
                    try {
                        System.out.println(client.getRemoteAddress().toString() + " connected! ");
                        while (client.isOpen()) {
                            byte[] arr = new byte[1024];
                            ByteBuffer buf = ByteBuffer.wrap(arr);
                            Future<Integer> read = client.read(buf);
                            if (read.get() == -1) {
                                System.out.println(client.getRemoteAddress().toString() + " closed! ");
                                client.close();
                            } else {
                                System.out.println("received data from client: " + client.getRemoteAddress().toString() + " ===> " + new String(arr));
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }

                @Override
                public void failed(Throwable exc, Object attachment) {
                    System.out.println("connected failed: " + exc.getMessage());

                }
            });
            // 暂停主程序，程序依然正常运行，说明异步
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

